package com.douyin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.douyin.constant.RedisConstant;
import com.douyin.entity.Follow;
import com.douyin.mapper.FollowMapper;
import com.douyin.service.FeedService;
import com.douyin.service.IFollowService;
import com.douyin.service.VideoService;
import com.douyin.utils.RedisCacheUtil;
import com.douyin.vo.BasePage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements IFollowService {

    @Autowired
    private RedisCacheUtil redisCacheUtil;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private FeedService feedService;
    @Autowired
    private VideoService videoService;
    @Override
    public long getFollowerCount(String userId) {
        return this.count(new LambdaQueryWrapper<Follow>().eq(Follow::getUserId,userId));
    }

    @Override
    public long getFansCount(String userId) {
        return this.count(new LambdaQueryWrapper<Follow>().eq(Follow::getFollowId,userId));
    }

    @Override
    public List<Long> getFollow(Long userId, BasePage basePage) {
        if (basePage == null) {
            final Set<Object> set = redisCacheUtil.zGet(RedisConstant.USER_FOLLOW + userId);
            if (ObjectUtils.isEmpty(set)){
                return Collections.EMPTY_LIST;
            }
            return set.stream().map(o->Long.valueOf(o.toString())).collect(Collectors.toList());
        }
        final Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisCacheUtil.zSetGetByPage(RedisConstant.USER_FOLLOW + userId, basePage.getPage(), basePage.getLimit());
        // 可能redis崩了,从db拿
        if (ObjectUtils.isEmpty(typedTuples)) {
            final List<Follow> follows = page(basePage.page(),new LambdaQueryWrapper<Follow>().eq(Follow::getUserId, userId).orderByDesc(Follow::getGmtCreated)).getRecords();
            if (ObjectUtils.isEmpty(follows)) {
                return Collections.EMPTY_LIST;
            }
            return follows.stream().map(Follow::getFollowId).collect(Collectors.toList());
        }
        return typedTuples.stream().map(t -> Long.parseLong(t.getValue().toString())).collect(Collectors.toList());
    }




    @Override
    public List<Long> getFans(Long userId, BasePage basePage) {
        if (basePage == null) {
            final Set<Object> set = redisCacheUtil.zGet(RedisConstant.USER_FANS + userId);
            if(ObjectUtils.isEmpty(set)){
                return Collections.EMPTY_LIST;
            }
            return set.stream().map(o->Long.valueOf(o.toString())).collect(Collectors.toList());
        }
        final Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisCacheUtil.zSetGetByPage(RedisConstant.USER_FANS + userId, basePage.getPage(), basePage.getLimit());
        if (ObjectUtils.isEmpty(typedTuples)) {
            final List<Follow> follows = page(basePage.page(),new LambdaQueryWrapper<Follow>().eq(Follow::getFollowId, userId)).getRecords();
            if (ObjectUtils.isEmpty(follows)){
                return Collections.EMPTY_LIST;
            }
            return follows.stream().map(Follow::getUserId).collect(Collectors.toList());
        }
        return typedTuples.stream().map(t -> Long.parseLong(t.getValue().toString())).collect(Collectors.toList());
    }

    @Override
    public Boolean follows(Long followId, Long userId) {
        if (followId==userId){
            throw new RuntimeException("不能关注自己");
        }
        Follow follow = new Follow();
        follow.setFollowId(followId);
        follow.setUserId(userId);
       try {
            //存入数据库
            this.save(follow);
            Date date = new Date();
            //将要关注的用户id存入我的关注列表缓存
            redisTemplate.opsForZSet().add(RedisConstant.USER_FOLLOW+userId,followId,date.getTime());
            //将我的id存入要关注用户的粉丝列表缓存
            redisTemplate.opsForZSet().add(RedisConstant.USER_FANS+followId,userId,date.getTime());

        }catch (Exception e){
            //取关
            this.remove(new LambdaQueryWrapper<Follow>().eq(Follow::getFollowId,followId).eq(Follow::getUserId,userId));
           List<Long> videoIds = (List<Long>) videoService.listVideoIdByUserId(followId);
           feedService.deleteInBoxFeed(userId,videoIds);
            //删除我的关注列表缓存
            redisTemplate.opsForZSet().remove(RedisConstant.USER_FOLLOW+userId,followId);
            //删除要关注用户的粉丝列表缓存
            redisTemplate.opsForZSet().remove(RedisConstant.USER_FANS+followId,userId);
            return false;
        }
        return true;
    }

    @Override
    public Boolean isFollows(Long followId, Long userId) {
        if (followId==null||userId==null)return false;
        return count(new LambdaQueryWrapper<Follow>().eq(Follow::getFollowId,followId).eq(Follow::getUserId,userId))==1;
    }
}
